package dispinfo.gismeteo;

import java.io.*;
import java.util.Hashtable;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;

import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import dispinfo.Lib;
import dispinfo.Provider;

public class GismeteoProvider extends Provider
{
	private int cityNum = 28722;
	private Vector dataItems;
	private String city;
	
	private Object dataItemsSynch = new Object();
	private static Font bigFont;
	
	static
	{
		bigFont = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE);
	}

	public GismeteoProvider()
	{
	}
	
	public int getRequestDataPeriod()
	{
		return 3*60*60;
	}
	
	private static String decodeCityString(String str)
	{
		StringBuffer result = new StringBuffer();
		
		for (int i = 0; i < str.length(); i++)
		{
			char chr = str.charAt(i); 
			if (chr == '%')
			{
				String valStr = str.substring(i+1, i+3); 
				int val = Integer.parseInt(valStr, 16);
				result.append(Lib.bytesToString(new byte[]{(byte)val}, Lib.CODING_WIN1251));
				i += 2;
			}
			else result.append(chr);
		}
		
		return result.toString();
	}
	
	private void readFromXml(InputStream is, Hashtable result) throws XmlPullParserException, IOException
	{
		int maxTemp = 0, minTemp = 0, cloudiness = 0, precipitation = 0, day = 0, month = 0, tod = 0;
		int minWind = 0, maxWind = 0, windDir = 0;
		Vector newIems = new Vector();
		String newCity = null;
		
		Reader reader = new InputStreamReader(is);
		
		KXmlParser xmlParser = new KXmlParser();
		
		xmlParser.setInput(reader);
		
		xmlParser.nextTag();
		xmlParser.require(XmlPullParser.START_TAG, null, "MMWEATHER");
		
		xmlParser.nextTag();
		xmlParser.require(XmlPullParser.START_TAG, null, "REPORT");
		String type = xmlParser.getAttributeValue(null, "type");
		System.out.println("type="+type);
		
		xmlParser.nextTag();
		xmlParser.require(XmlPullParser.START_TAG, null, "TOWN");
		String index = xmlParser.getAttributeValue(null, "index");
		newCity = decodeCityString(xmlParser.getAttributeValue(null, "sname"));
		System.out.println("index="+index+", newCity="+newCity);
		
		while(xmlParser.nextTag() == XmlPullParser.START_TAG) 
		{
			xmlParser.require(XmlPullParser.START_TAG, null, "FORECAST");
			
			day = Integer.parseInt(xmlParser.getAttributeValue(null, "day"));
			month = Integer.parseInt(xmlParser.getAttributeValue(null, "month"));
			tod = Integer.parseInt(xmlParser.getAttributeValue(null, "tod"));
		
			while(xmlParser.nextTag() == XmlPullParser.START_TAG)
			{
				
				String tagName = xmlParser.getName();
			
				if ("TEMPERATURE".equalsIgnoreCase(tagName))
				{
					maxTemp = Integer.parseInt(xmlParser.getAttributeValue(null, "max"));
					minTemp = Integer.parseInt(xmlParser.getAttributeValue(null, "min"));
				}
				
				if ("PHENOMENA".equalsIgnoreCase(tagName))
				{
					cloudiness = Integer.parseInt(xmlParser.getAttributeValue(null, "cloudiness"));
					precipitation = Integer.parseInt(xmlParser.getAttributeValue(null, "precipitation"));
				}
				
				if ("WIND".equalsIgnoreCase(tagName))
				{
					minWind = Integer.parseInt(xmlParser.getAttributeValue(null, "min"));
					maxWind = Integer.parseInt(xmlParser.getAttributeValue(null, "max"));
					windDir = Integer.parseInt(xmlParser.getAttributeValue(null, "direction"));
				}
				
				xmlParser.nextTag();
			}
			
			GismeteoDataItem newItem = new GismeteoDataItem(day, month, tod, cloudiness, precipitation, minTemp, 
					maxTemp, minWind, maxWind, windDir);
			
			newIems.addElement(newItem);

			xmlParser.require(XmlPullParser.END_TAG, null, "FORECAST");
		}
		
		synchronized (dataItemsSynch)
		{
			dataItems = newIems;
			city = newCity;
		}
	}

	public void requestData()
	{
		InputStream is = null;
		HttpConnection httpConn = null;
		
		try
		{
			httpConn = (HttpConnection)Connector.open("http://informer.gismeteo.ru/xml/"+cityNum+"_1.xml", Connector.READ_WRITE);
			httpConn.setRequestMethod("GET");
			
			int respCode = httpConn.getResponseCode();
			if (respCode != HttpConnection.HTTP_OK) throw new Exception("Server error: "+respCode);
			
			is = httpConn.openInputStream();
			
			Hashtable result = new Hashtable();
			
			readFromXml(is, result);
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		finally
		{
			if (is != null) try { is.close(); } catch (Exception e) {}
			if (httpConn != null) try { httpConn.close(); } catch (Exception e) {}
		}
	}

	public void paint(Graphics g, int width, int height)
	{
		// Рисуем фон
		g.setColor(0xFFFFFF);
		g.fillRect(0, 0, width, height);
		
		// Забираем данные
		Vector items;
		String city;
		synchronized (dataItemsSynch)
		{
			items = this.dataItems;
			city = this.city;
		}
		
		if (items == null) return;
		if (city == null) return;
		
		int bigFontHeight = bigFont.getHeight(); 

		// Вычисялем высоту
		int size = items.size();
		int itemsHeight = bigFontHeight; 
		for (int i = 0; i < size; i++)
		{
			GismeteoDataItem item = (GismeteoDataItem)items.elementAt(i);
			itemsHeight += item.getHeight();
		}

		// Отрисовываем
		int y = (height-itemsHeight)/2;
		g.setColor(0x808080);
		g.setFont(bigFont);
		g.drawString(city, bigFontHeight/2, y, Graphics.TOP|Graphics.LEFT);
		y += bigFont.getHeight();
		for (int i = 0; i < size; i++)
		{
			GismeteoDataItem item = (GismeteoDataItem)items.elementAt(i);
			int itemHeight = item.getHeight();
			item.paint(g, 0, y, width, itemHeight);
			g.setColor(0xC0C0C0);
			g.drawLine(0, y, width, y);
			y += itemHeight;
		}
	
	}

	public int getHeight()
	{
		// TODO Auto-generated method stub
		return 0;
	}

}
